package com.liu.qqRobot.wm.handler;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.liu.common.utils.HtmlToImageUtils;
import com.liu.common.utils.QQClientUtils;
import com.liu.common.utils.WmClientUtils;
import com.liu.mybatisPlus.q.service.QGroupUserOperationQuantityService;
import com.liu.mybatisPlus.wm.entity.base.WmRivenAttributes;
import com.liu.mybatisPlus.wm.entity.base.WmRivenAttributesKeyWord;
import com.liu.mybatisPlus.wm.entity.base.WmRivenItem;
import com.liu.mybatisPlus.wm.entity.base.WmRivenItemKeyWord;
import com.liu.mybatisPlus.wm.service.WmRivenAttributesKeyWordService;
import com.liu.mybatisPlus.wm.service.WmRivenAttributesService;
import com.liu.mybatisPlus.wm.service.WmRivenItemKeyWordService;
import com.liu.mybatisPlus.wm.service.WmRivenItemService;
import com.liu.qqRobot.event.entity.dto.EventReportingDTO;
import com.liu.qqRobot.q.enums.OperationTypeEnum;
import com.liu.qqRobot.wm.entity.dto.WarframeMarketRivenAuctionDTO;
import com.liu.qqRobot.wm.entity.dto.WarframeMarketRivenAuctionTemplateDTO;
import com.liu.qqRobot.wm.enums.AuctionsSortByEnum;
import freemarker.template.TemplateException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class WmrHandler {

    @Resource
    private WmRivenItemService wmRivenItemService;

    @Resource
    private WmRivenItemKeyWordService wmRivenItemKeyWordService;

    @Resource
    private WmRivenAttributesService wmRivenAttributesService;

    @Resource
    private WmRivenAttributesKeyWordService wmRivenAttributesKeyWordService;

    @Resource
    private QGroupUserOperationQuantityService qGroupUserOperationQuantityService;

    /**
     * 处理事件
     * @param data 信息内容
     * @param groupId 群号
     * @param userId 发送人QQ号
     */
    public void handler(EventReportingDTO.Message.Data data, Long groupId, Long userId, Boolean isGroup) {
        int page = 1;
        String text = data.getText();
        // 是否零洗
        boolean isZero = false;
        if (text.contains("零洗")) {
            isZero = true;
            text = text.replace("零洗", "");
        }

        String[] textSplit = text.split(" ");

        // 获取需要查询紫卡信息的物品名称
        WmRivenItem wmRivenItem = null;
        String itemName = textSplit[textSplit.length - 1];
        QueryWrapper<WmRivenItemKeyWord> wmRivenKeyWordQueryWrapper = new QueryWrapper<>();
        wmRivenKeyWordQueryWrapper.eq("key_word", itemName);
        WmRivenItemKeyWord wmRivenItemKeyWord = wmRivenItemKeyWordService.getOne(wmRivenKeyWordQueryWrapper);
        if (wmRivenItemKeyWord != null) {
            wmRivenItem = wmRivenItemService.getById(wmRivenItemKeyWord.getId());
        } else {
            QueryWrapper<WmRivenItem> wmRivenItemQueryWrapper = new QueryWrapper<>();
            wmRivenItemQueryWrapper.eq("item_name", itemName);
            wmRivenItem = wmRivenItemService.getOne(wmRivenItemQueryWrapper);
        }
        if (wmRivenItem == null) {
            return;
        }

        // 获取需要查询的正/负向属性
        List<String> attributesList = new ArrayList<>();
        for (int i = 0; i < textSplit.length; i++) {
            if (i != 0 && i < textSplit.length - 1) {
                attributesList.add(textSplit[i]);
            }
        }
        List<String> positiveStatsList = new ArrayList<>(3);
        List<String> negativeStatsList = new ArrayList<>(3);
        List<WmRivenAttributesKeyWord> wmRivenAttributesKeyWords = wmRivenAttributesKeyWordService.list();
        Map<String, String> wmRivenAttributesKeyWordMap = wmRivenAttributesKeyWords.stream().collect(Collectors.toMap(WmRivenAttributesKeyWord::getKeyWord, WmRivenAttributesKeyWord::getId));
        attributesList.forEach(attributes -> {
            WmRivenAttributes wmRivenAttributes;
            if (attributes.contains("负")) {
                attributes = attributes.replace("负", "");
                String attributesId = wmRivenAttributesKeyWordMap.get(attributes);
                if (attributesId == null) {
                    QueryWrapper<WmRivenAttributes> wmRivenAttributesQueryWrapper = new QueryWrapper<>();
                    wmRivenAttributesQueryWrapper.eq("effect", attributes);
                    wmRivenAttributes = wmRivenAttributesService.getOne(wmRivenAttributesQueryWrapper);
                } else {
                    wmRivenAttributes = wmRivenAttributesService.getById(attributesId);
                }
                if (wmRivenAttributes != null) {
                    negativeStatsList.add(wmRivenAttributes.getUrlName());
                }
            } else {
                String attributesId = wmRivenAttributesKeyWordMap.get(attributes);
                if (attributesId == null) {
                    QueryWrapper<WmRivenAttributes> wmRivenAttributesQueryWrapper = new QueryWrapper<>();
                    wmRivenAttributesQueryWrapper.eq("effect", attributes);
                    wmRivenAttributes = wmRivenAttributesService.getOne(wmRivenAttributesQueryWrapper);
                } else {
                    wmRivenAttributes = wmRivenAttributesService.getById(attributesId);
                }
                if (wmRivenAttributes != null) {
                    positiveStatsList.add(wmRivenAttributes.getUrlName());
                }
            }
        });

        List<WarframeMarketRivenAuctionDTO> warframeMarketRivenAuctionDTOList =
                WmClientUtils.getRivenAuctions("riven", null, wmRivenItem.getUrlName(),
                        CollUtil.join(positiveStatsList, ","), CollUtil.join(negativeStatsList, ","), null,
                        null, null, isZero ? 0:null, isZero ? 0:null, null,
                        null, AuctionsSortByEnum.PRICE_ASC.getType());
        // 判断排序
        warframeMarketRivenAuctionDTOList.forEach(warframeMarketItemsOrderDTO -> {
            warframeMarketItemsOrderDTO.setSort(this.getSortByStatus(warframeMarketItemsOrderDTO.getOwner().getStatus()));
        });
        // 排序 ingame-1 online-2 offline-3，后排序价格
        warframeMarketRivenAuctionDTOList = warframeMarketRivenAuctionDTOList.stream()
                .sorted(Comparator.comparing(WarframeMarketRivenAuctionDTO::getSort).thenComparing(WarframeMarketRivenAuctionDTO::getStartingPrice))
                .collect(Collectors.toList());
        List<List<WarframeMarketRivenAuctionDTO>> warframeMarketRivenAuctionDTOListSplit = ListUtil.split(warframeMarketRivenAuctionDTOList, 5);
        List<WarframeMarketRivenAuctionTemplateDTO> warframeMarketRivenAuctionTemplateDTOList = new ArrayList<>();
        for (int i = 0; i < warframeMarketRivenAuctionDTOListSplit.size(); i++) {
            List<WarframeMarketRivenAuctionDTO> warframeMarketRivenAuctionDTOS = warframeMarketRivenAuctionDTOListSplit.get(page - 1);
            for (WarframeMarketRivenAuctionDTO warframeMarketRivenAuctionDTO : warframeMarketRivenAuctionDTOS) {
                WarframeMarketRivenAuctionTemplateDTO warframeMarketRivenAuctionTemplateDTO = new WarframeMarketRivenAuctionTemplateDTO();
                warframeMarketRivenAuctionTemplateDTO.setStartingPrice(String.valueOf(warframeMarketRivenAuctionDTO.getStartingPrice()));
                warframeMarketRivenAuctionTemplateDTO.setBuyoutPrice(String.valueOf(warframeMarketRivenAuctionDTO.getBuyoutPrice()));
                warframeMarketRivenAuctionTemplateDTO.setTopBid(warframeMarketRivenAuctionDTO.getTopBid() == null ? "暂无" : String.valueOf(warframeMarketRivenAuctionDTO.getTopBid()));
                warframeMarketRivenAuctionTemplateDTO.setIngameName(warframeMarketRivenAuctionDTO.getOwner().getIngameName());
                warframeMarketRivenAuctionTemplateDTO.setStatus(this.getStatusDesc(warframeMarketRivenAuctionDTO.getOwner().getStatus()));
                warframeMarketRivenAuctionTemplateDTO.setModRank(String.valueOf(warframeMarketRivenAuctionDTO.getItem().getModRank()));
                warframeMarketRivenAuctionTemplateDTO.setMasteryLevel(String.valueOf(warframeMarketRivenAuctionDTO.getItem().getMasteryLevel()));
                warframeMarketRivenAuctionTemplateDTO.setReRolls(String.valueOf(warframeMarketRivenAuctionDTO.getItem().getReRolls()));
                warframeMarketRivenAuctionTemplateDTO.setPolarity(warframeMarketRivenAuctionDTO.getItem().getPolarity());
                warframeMarketRivenAuctionTemplateDTO.setItemName(wmRivenItem.getItemName() + " " + warframeMarketRivenAuctionDTO.getItem().getName());
                List<WarframeMarketRivenAuctionDTO.Item.Attribute> modPositiveStatsList = warframeMarketRivenAuctionDTO.getItem().getAttributes().stream().filter(WarframeMarketRivenAuctionDTO.Item.Attribute::getPositive).toList();
                List<WarframeMarketRivenAuctionDTO.Item.Attribute> modNegativeStatsList = warframeMarketRivenAuctionDTO.getItem().getAttributes().stream().filter(a -> !a.getPositive()).toList();
                List<String> attributeUrlNameList = warframeMarketRivenAuctionDTO.getItem().getAttributes().stream().map(WarframeMarketRivenAuctionDTO.Item.Attribute::getUrlName).collect(Collectors.toList());
                QueryWrapper<WmRivenAttributes> wmRivenAttributesQueryWrapper = new QueryWrapper<>();
                wmRivenAttributesQueryWrapper.in("url_name", attributeUrlNameList);
                List<WmRivenAttributes> wmRivenAttributesList = wmRivenAttributesService.list(wmRivenAttributesQueryWrapper);
                Map<String, WmRivenAttributes> wmRivenAttributesMap = wmRivenAttributesList.stream().collect(Collectors.toMap(WmRivenAttributes::getUrlName, a -> a));
                StringBuilder modPositiveStats = new StringBuilder();
                for (WarframeMarketRivenAuctionDTO.Item.Attribute attribute : modPositiveStatsList) {
                    WmRivenAttributes attributes = wmRivenAttributesMap.get(attribute.getUrlName());
                    modPositiveStats.append("+").append(attributes.getEffect()).append(this.getUnitValue(attributes.getUnits(), attribute.getValue())).append("   ");
                }
                warframeMarketRivenAuctionTemplateDTO.setPositiveStats(modPositiveStats.toString());
                StringBuilder modNegativeStats = new StringBuilder();
                for (WarframeMarketRivenAuctionDTO.Item.Attribute attribute : modNegativeStatsList) {
                    WmRivenAttributes attributes = wmRivenAttributesMap.get(attribute.getUrlName());
                    modNegativeStats.append("-").append(attributes.getEffect()).append(this.getUnitValue(attributes.getUnits(), attribute.getValue())).append("   ");
                }
                warframeMarketRivenAuctionTemplateDTO.setNegativeStats(StrUtil.isEmpty(modNegativeStats.toString()) ? null : modNegativeStats.toString());
                warframeMarketRivenAuctionTemplateDTOList.add(warframeMarketRivenAuctionTemplateDTO);
            }
            break;
        }
        if (CollUtil.isEmpty(warframeMarketRivenAuctionTemplateDTOList)) {
            String msg = "[CQ:at,qq=" + userId + "]\n目前未在warframe.market查询到相关交易";
            return;
        }
        Map<String, Object> templateParam = new HashMap<>();
        StringBuilder baseName = new StringBuilder(wmRivenItem.getItemName());
        if (isZero) {
            baseName.insert(0, "零洗");
        }
        for (String attributes : attributesList) {
            baseName.insert(0, attributes + " ");
        }
        templateParam.put("baseName", baseName.toString());
        templateParam.put("auctionList", warframeMarketRivenAuctionTemplateDTOList);
        try {
            HtmlToImageUtils.htmlToImage("rivenAuctionTemplate.html", templateParam, "src/main/resources/picture/rivenAuction.png", 2600);
            File file = new File("src/main/resources/picture/rivenAuction.png");
            String encode = Base64.encode(file);
            String msg = "[CQ:at,qq=" + userId + "]\n[CQ:image,file=base64://" + encode+ ",type=show,subType=0]";
            QQClientUtils.sendMsg(msg, userId, groupId, isGroup);
            qGroupUserOperationQuantityService.statisticsOperationQuantityByType(groupId, userId, OperationTypeEnum.WMR);
        } catch (IOException | TemplateException | ParserConfigurationException | SAXException e) {
            log.error("获取紫卡展示模板失败:{}", e.getMessage(), e);
        }
    }

    /**
     * 解析状态判断排序
     * @param status offline ingame online
     * @return String
     */
    private Integer getSortByStatus(String status) {
        return switch (status) {
            case "offline" -> 3;
            case "ingame" -> 1;
            case "online" -> 2;
            default -> 4;
        };
    }

    /**
     * 解析状态为中文
     * @param status offline ingame online
     * @return String
     */
    private String getStatusDesc(String status) {
        return switch (status) {
            case "offline" -> "离线";
            case "ingame" -> "游戏中";
            case "online" -> "在线";
            default -> "";
        };
    }

    /**
     * 解析属性值单位
     * @param unit 单位
     * @return String
     */
    private String getUnitValue(String unit, BigDecimal value) {
        if (StrUtil.isEmpty(unit)) {
            return value.setScale(2, RoundingMode.HALF_UP).toString();
        } else {
            return switch (unit) {
                case "percent" -> value.setScale(2, RoundingMode.HALF_UP) + "%";
                case "multiply" -> "X" + value.setScale(2, RoundingMode.HALF_UP);
                case "seconds" -> value.setScale(2, RoundingMode.HALF_UP) + "秒";
                default -> value.setScale(2, RoundingMode.HALF_UP).toString();
            };
        }
    }
}
